Etudes Sur les sinistres automobiles corporels

Ce projet a été realisé par le groupe DataDigger :

  • Allaoui Hayfa
  • Amri Nader
  • Bedoui Aymen
  • Ben Mohamed Ahmed
  • Khanfir Sofien
  • Masmoudi Skander

Introduction

De nos jours, avec la mécanisation de tous les secteurs de l'économie et surtout de la modernisation de plus en plus poussée du trafic routier, nous assistons à une augmentation exponentielle du nombre d'accidents de la route. Cette hécatombe et cette somme de souffrances, qui frappent tout particulièrement les jeunes n'épargnent aucun pays. Un patrimoine humain considérable se trouve ainsi anéanti, entraînant avec lui de très lourdes conséquences sociales et économiques. Si les actuelles statistiques sont déjà alarmantes, les tendances le seront encore plus.Les accidents de la circulation seront alors l'une des principales causes de morbidité dans le monde. Ce fardeau pèse plus lourdement sur les pays à faible revenu et les pays à revenu intermédiaire . Mieux connaître ce problème et ses multiples déterminants, en identifier les acteurs, nombreux et dispersés, en comprendre le contexte et les enjeux, chasser quelques idées reçues comme« les accidents interviennent surtout quand le trafic est dense, quelques km/h de plus, ce n'est pas bien dangereux... » Grâce à la contribution d'auteurs d'horizons variés, nous essayerons de croiser les regards, de générer des idées, afin d'améliorer la politique de prévention des accidents de la circulation dans ces deux pays.

Objectives Business

Dans ce projet notre objective c'est de :

  • Trouver des solutions afin de pouvoir limiter le nombre d'accident
  • Determiner les causes des accidents
  • Determiner la commune ayant le plus de nombre d'accident
  • Prédire la gravité des accidents en 2018

Datascience Goals

Notre objective DataScience est de :

Dans ce projet nous aurons recourt a la methode CRISP

Importation des Données

Dans ce projet nous avons travaillé sur les Dataset suivants :

  • vehicule.csv
  • usagers.csv
  • lieux.csv
  • caractéristique.csv
Pour chaque année depuis 2005 jusqu'a 2017 nous avons ensuite fait une jointure sur la colonnes Num_Acc Afin de pouvoir avoir une seule base de donnée . Apres avoir regroupé les colonnes on a regroupé les données de toutes les années .

In [5]:
import pandas as pd 
import sql
from pyspark import SparkContext
from pyspark.sql import SQLContext
In [2]:
Data=pd.read_csv(r'C:\Users\pc\AllDataFrames.csv',encoding='utf-8-sig')
C:\Users\pc\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:2785: DtypeWarning: Columns (13,14,15,16,19,21) have mixed types. Specify dtype option on import or set low_memory=False.
  interactivity=interactivity, compiler=compiler, result=result)
In [3]:
Data.head(6)
Out[3]:
Unnamed: 0 Num_Acc an mois jour hrmn lum agg int atm ... num_veh Num_Acc..47 senc catv occutc obs obsm choc manv num_veh..55
0 1 200500000001 5 1 12 1900 3 2 1 1.0 ... B02 200500000001 0.0 7 0 0.0 2.0 1.0 1.0 A01
1 2 200500000001 5 1 12 1900 3 2 1 1.0 ... B02 200500000001 0.0 7 0 0.0 2.0 8.0 10.0 B02
2 3 200500000001 5 1 12 1900 3 2 1 1.0 ... A01 200500000001 0.0 7 0 0.0 2.0 1.0 1.0 A01
3 4 200500000001 5 1 12 1900 3 2 1 1.0 ... A01 200500000001 0.0 7 0 0.0 2.0 8.0 10.0 B02
4 5 200500000001 5 1 12 1900 3 2 1 1.0 ... B02 200500000001 0.0 7 0 0.0 2.0 1.0 1.0 A01
5 6 200500000001 5 1 12 1900 3 2 1 1.0 ... B02 200500000001 0.0 7 0 0.0 2.0 8.0 10.0 B02

6 rows × 56 columns

Preparation des données

Dans un premier temps on a voulu avoir le nom de la commune pour chaque département donnée on a donc travailler sur un jeu de donnée récupéré depuis le site afin de pouvoir avoir le nom de chaque commune et le code INSEE . Source : https://public.opendatasoft.com/explore/dataset/correspondance-code-insee-code-postal/table/?fbclid=IwAR2tPVM81qBlCS5nH5Z2zsQVclhFq23WY3he_fJcHMkGFbJxWVbONuXFsZA

In [4]:
import numpy
Data = Data.replace('', numpy.NaN)
dep1 = [numpy.NaN,'-','0']
com1 = [numpy.NaN,0]
dep2 = ['10','20','30','40','50','60','70','80','90','4']

newData = Data[~Data.dep.isin(dep1)]
newData = newData[~newData.com.isin(com1)]
newData = newData.dropna(subset = ['com'])
newData.com = newData.com.apply(lambda x: str(x)[0:-2])
newData.com = newData.com.apply(lambda x: '00'+x if len(x)==1 else x)
newData.com = newData.com.apply(lambda x: '0'+x if len(x)==2 else x)
newData.dep = newData.dep.apply(lambda x: '0'+x[0] if x in dep2 else x)
newData.dep = newData.dep.apply(lambda x: str(x)[0:-1] if str(x)[-1]=='0' else x)
newData.dep = newData.dep.apply(lambda x: str(x).replace('201','2A'))
newData.dep = newData.dep.apply(lambda x: str(x).replace('202','2B'))
newData['dep_com']=newData.dep + newData.com

On a ensuite fait la jointure entre le code INSEE et dep_com pour avoir la dataset suivante :

In [6]:
final=pd.read_csv(r'C:\Users\pc\Documents\final3.csv',sep=";")
C:\Users\pc\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:2785: DtypeWarning: Columns (15,17,18,21,23,26,58) have mixed types. Specify dtype option on import or set low_memory=False.
  interactivity=interactivity, compiler=compiler, result=result)
In [7]:
final.head(10)
Out[7]:
Unnamed: 0 X Unnamed..0 Num_Acc an mois jour hrmn lum agg ... senc catv occutc obs obsm choc manv num_veh..55 dep_com NomCommune
0 1 0 1 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 1.0 1.0 A01 59011 ANNOEULLIN
1 2 1 2 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 8.0 10.0 B02 59011 ANNOEULLIN
2 3 2 3 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 1.0 1.0 A01 59011 ANNOEULLIN
3 4 3 4 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 8.0 10.0 B02 59011 ANNOEULLIN
4 5 4 5 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 1.0 1.0 A01 59011 ANNOEULLIN
5 6 5 6 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 8.0 10.0 B02 59011 ANNOEULLIN
6 7 6 7 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 1.0 1.0 A01 59011 ANNOEULLIN
7 8 7 8 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 8.0 10.0 B02 59011 ANNOEULLIN
8 9 8 9 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 1.0 1.0 A01 59011 ANNOEULLIN
9 10 9 10 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 8.0 10.0 B02 59011 ANNOEULLIN

10 rows × 60 columns

In [8]:
list(final.columns)
Out[8]:
['Unnamed: 0',
 'X',
 'Unnamed..0',
 'Num_Acc',
 'an',
 'mois',
 'jour',
 'hrmn',
 'lum',
 'agg',
 'int',
 'atm',
 'col',
 'com',
 'adr',
 'gps',
 'lat',
 'long',
 'dep',
 'Num_Acc..17',
 'catr',
 'voie',
 'v1',
 'v2',
 'circ',
 'nbv',
 'pr',
 'pr1',
 'vosp',
 'prof',
 'plan',
 'lartpc',
 'larrout',
 'surf',
 'infra',
 'situ',
 'env1',
 'Num_Acc..35',
 'place',
 'catu',
 'grav',
 'sexe',
 'trajet',
 'secu',
 'locp',
 'actp',
 'etatp',
 'an_nais',
 'num_veh',
 'Num_Acc..47',
 'senc',
 'catv',
 'occutc',
 'obs',
 'obsm',
 'choc',
 'manv',
 'num_veh..55',
 'dep_com',
 'NomCommune']

on peut remarquer la présence des variables dupliqué on va donc les supprimers

In [9]:
final=final.drop(['Unnamed: 0','X','Unnamed..0','Num_Acc..17','Num_Acc..35','Num_Acc..47','num_veh..55'],1)
In [10]:
final.head()
Out[10]:
Num_Acc an mois jour hrmn lum agg int atm col ... num_veh senc catv occutc obs obsm choc manv dep_com NomCommune
0 200500000001 5 1 12 1900 3 2 1 1.0 3.0 ... B02 0.0 7 0 0.0 2.0 1.0 1.0 59011 ANNOEULLIN
1 200500000001 5 1 12 1900 3 2 1 1.0 3.0 ... B02 0.0 7 0 0.0 2.0 8.0 10.0 59011 ANNOEULLIN
2 200500000001 5 1 12 1900 3 2 1 1.0 3.0 ... A01 0.0 7 0 0.0 2.0 1.0 1.0 59011 ANNOEULLIN
3 200500000001 5 1 12 1900 3 2 1 1.0 3.0 ... A01 0.0 7 0 0.0 2.0 8.0 10.0 59011 ANNOEULLIN
4 200500000001 5 1 12 1900 3 2 1 1.0 3.0 ... B02 0.0 7 0 0.0 2.0 1.0 1.0 59011 ANNOEULLIN

5 rows × 53 columns

On va remplacer ensuite les variables manquantes avec la methode random

In [11]:
from scipy import stats
import random
while final.isna().any().any()==True:
    for i in final.columns:
        final[i] = final[i].fillna(random.choice(final[i]))

Nous allons ensuite regrouper les données par commune dans chaque année : on va commencer par rendre les variables muettes pour arriver a faire la somme des variables .

In [22]:
def OHE(df):
    #col = df.select_dtypes(include=['category']).columns
    col = ['lum','atm','col','agg','catr','circ','prof','plan','situ','obs','obsm','catu','grav','sexe','trajet','secu','actp','etatp']
    print('Categorical columns in dataset',col)
    
    c2,c3 = [],{}
    for c in col:
        if df[c].nunique()>2 :
            c2.append(c)
            c3[c] = 'ohe_'+c
    
    df = pd.get_dummies(df,columns=c2,drop_first=True,prefix=c3)
    print(df.shape)
    return df
In [23]:
DummiedData=OHE(final)
Categorical columns in dataset ['lum', 'atm', 'col', 'agg', 'catr', 'circ', 'prof', 'plan', 'situ', 'obs', 'obsm', 'catu', 'grav', 'sexe', 'trajet', 'secu', 'actp', 'etatp']
(3366039, 145)
In [24]:
DummiedData.columns
Out[24]:
Index(['Num_Acc', 'an', 'mois', 'jour', 'hrmn', 'agg', 'int', 'com', 'adr',
       'gps',
       ...
       'ohe_actp_1.0', 'ohe_actp_2.0', 'ohe_actp_3.0', 'ohe_actp_4.0',
       'ohe_actp_5.0', 'ohe_actp_6.0', 'ohe_actp_9.0', 'ohe_etatp_1.0',
       'ohe_etatp_2.0', 'ohe_etatp_3.0'],
      dtype='object', length=145)
In [25]:
DummiedData.to_csv('DumiedData20052017.csv',index = False,sep=';')
In [30]:
sc =SparkContext.getOrCreate()
sql_ctx = SQLContext(sc)
df = sql_ctx.read.format('com.databricks.spark.csv').options(delimiter=';',header='true').load('DumiedData20052017.csv')
In [27]:
df.registerTempTable("DataSQL")
results = sql_ctx.sql("SELECT NomCommune, an, count(*) as nb_acc_tot ,sum(ohe_lum_2) as nb_acc_lum2 ,sum(ohe_lum_3) as nb_acc_lum3,sum(ohe_lum_4) as nb_acc_lum4,sum(ohe_lum_5) as nb_acc_lum5,sum(`ohe_catr_2.0`) as nb_acc_catr2,sum(`ohe_catr_3.0`) as nb_acc_catr3,sum(`ohe_catr_4.0`) as nb_acc_catr4,sum(`ohe_catr_5.0`) as nb_acc_catr5,sum(`ohe_catr_6.0`) as nb_acc_catr6,sum(`ohe_catr_9.0`) as nb_acc_catr9,sum(ohe_catu_2) as nb_acc_catu2,sum(ohe_catu_3) as nb_acc_catu3,sum(ohe_catu_4) as nb_acc_catu4,sum(`ohe_atm_2.0`) as nb_acc_atm2,sum(`ohe_atm_3.0`) as nb_acc_atm3,sum(`ohe_atm_4.0`) as nb_acc_atm4,sum(`ohe_atm_5.0`) as nb_acc_atm5,sum(`ohe_atm_6.0`) as nb_acc_atm6,sum(`ohe_atm_7.0`) as nb_acc_atm7,sum(`ohe_atm_8.0`) as nb_acc_atm8,sum(`ohe_atm_9.0`) as nb_acc_atm9,sum(`ohe_prof_1.0`) as nb_acc_prof1,sum(`ohe_prof_2.0`) as nb_acc_prof2,sum(`ohe_prof_3.0`) as nb_acc_prof3,sum(`ohe_prof_4.0`) as nb_acc_prof4,sum(ohe_grav_2) as nb_acc_grav2,sum(ohe_grav_3) as nb_acc_grav3,sum(ohe_grav_4) as nb_acc_grav4 FROM DataSQL GROUP BY NomCommune,an")
In [28]:
results.toPandas().to_csv('Aggregation.csv')
In [29]:
dataf =pd.read_csv('Aggregation.csv')
dataf.head(10)
Out[29]:
Unnamed: 0 NomCommune an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 ... nb_acc_atm7 nb_acc_atm8 nb_acc_atm9 nb_acc_prof1 nb_acc_prof2 nb_acc_prof3 nb_acc_prof4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4
0 0 FREIGNE 5 6 0.0 0.0 0.0 0.0 0.0 6.0 ... 0.0 6.0 0.0 0.0 0.0 0.0 6.0 0.0 2.0 4.0
1 1 PRANZAC 5 3 2.0 1.0 0.0 0.0 0.0 3.0 ... 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 2.0 0.0
2 2 LONGEVILLE-LES-SAINT-AVOLD 5 32 0.0 18.0 0.0 1.0 20.0 6.0 ... 0.0 4.0 0.0 5.0 23.0 0.0 0.0 0.0 6.0 19.0
3 3 BEAUREPAIRE-EN-BRESSE 5 6 0.0 6.0 0.0 0.0 6.0 0.0 ... 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0
4 4 CHALLES-LA-MONTAGNE 5 10 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 4.0 6.0 0.0 0.0 0.0 0.0 8.0
5 5 LA CHARITE-SUR-LOIRE 5 18 0.0 1.0 0.0 2.0 13.0 4.0 ... 0.0 0.0 0.0 17.0 1.0 0.0 0.0 0.0 3.0 3.0
6 6 LINSELLES 5 24 0.0 0.0 0.0 2.0 0.0 14.0 ... 0.0 0.0 0.0 24.0 0.0 0.0 0.0 0.0 7.0 10.0
7 7 SURESNES 5 315 23.0 2.0 0.0 73.0 4.0 217.0 ... 0.0 0.0 0.0 199.0 72.0 21.0 9.0 0.0 24.0 140.0
8 8 LE BLANC-MESNIL 5 246 1.0 0.0 0.0 86.0 20.0 38.0 ... 0.0 6.0 0.0 222.0 10.0 0.0 0.0 0.0 68.0 65.0
9 9 NOGUERES 5 1 0.0 1.0 0.0 0.0 0.0 1.0 ... 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0

10 rows × 32 columns

Compréhensiondes données

In [1]:
from IPython.core.display import display, HTML
display(HTML('<iframe width="800" height="600" src="https://app.powerbi.com/view?r=eyJrIjoiZWVlMGQxZWMtNTVjNi00Y2I1LTljODktMzQ5MTBhZjllZWRkIiwidCI6ImYwNjA4MDQxLTU1ZGMtNDJjNS1iY2FkLTUzNjIzZTFhY2FlNCIsImMiOjh9" frameborder="0" allowFullScreen="true"></iframe>'))

D'apres la visualisation des data on peut voir que

  • les hommes ont commis plus d'accident que les femmes
  • le nombre de sinistre en plein jour est beaucoup plus élevé que les autres .
  • l'age moyen des personnes qui ont commis des sinistres sont entre 30-40
  • les personnes tué presente une minorité par rapport aux personnes indemnes
  • La majorité des sinistres se sont produits lorsque la surface est normal mais il est existe une partie importante des sinistres s'est produit lorsque le sol etait mouillé
  • la majorité des collision est frontale

Modélisation

In [2]:
data = pd.read_csv("Aggregation(1).csv")
data_orgin = data
pd.set_option('display.max_columns', 500)
data = data.drop('Unnamed: 0', axis=1)
data.head()
Out[2]:
com an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3 nb_acc_catu4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4
0 59.0 5 687 15.0 136.0 0.0 79.0 247.0 300.0 122.0 0.0 2.0 5.0 199.0 18.0 0.0 40.0 181.0 207.0
1 267.0 5 314 19.0 37.0 0.0 46.0 76.0 140.0 79.0 0.0 2.0 10.0 85.0 8.0 0.0 21.0 50.0 122.0
2 182.0 5 539 21.0 36.0 0.0 49.0 68.0 274.0 98.0 0.0 8.0 6.0 183.0 14.0 0.0 32.0 109.0 138.0
3 906.0 5 16 0.0 15.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 6.0 0.0 0.0 4.0 6.0 2.0
4 136.0 6 1001 59.0 145.0 7.0 141.0 75.0 306.0 411.0 0.0 6.0 32.0 266.0 38.0 2.0 23.0 211.0 367.0
In [3]:
garv_score= data.nb_acc_grav2*100+data.nb_acc_grav4*10.8+data.nb_acc_grav4*0.44
data['Grav_Score'] = garv_score
data.head()
Out[3]:
com an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3 nb_acc_catu4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4 Grav_Score
0 59.0 5 687 15.0 136.0 0.0 79.0 247.0 300.0 122.0 0.0 2.0 5.0 199.0 18.0 0.0 40.0 181.0 207.0 6326.68
1 267.0 5 314 19.0 37.0 0.0 46.0 76.0 140.0 79.0 0.0 2.0 10.0 85.0 8.0 0.0 21.0 50.0 122.0 3471.28
2 182.0 5 539 21.0 36.0 0.0 49.0 68.0 274.0 98.0 0.0 8.0 6.0 183.0 14.0 0.0 32.0 109.0 138.0 4751.12
3 906.0 5 16 0.0 15.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 6.0 0.0 0.0 4.0 6.0 2.0 422.48
4 136.0 6 1001 59.0 145.0 7.0 141.0 75.0 306.0 411.0 0.0 6.0 32.0 266.0 38.0 2.0 23.0 211.0 367.0 6425.08
In [4]:
data.head()
Out[4]:
com an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3 nb_acc_catu4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4 Grav_Score
0 59.0 5 687 15.0 136.0 0.0 79.0 247.0 300.0 122.0 0.0 2.0 5.0 199.0 18.0 0.0 40.0 181.0 207.0 6326.68
1 267.0 5 314 19.0 37.0 0.0 46.0 76.0 140.0 79.0 0.0 2.0 10.0 85.0 8.0 0.0 21.0 50.0 122.0 3471.28
2 182.0 5 539 21.0 36.0 0.0 49.0 68.0 274.0 98.0 0.0 8.0 6.0 183.0 14.0 0.0 32.0 109.0 138.0 4751.12
3 906.0 5 16 0.0 15.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 6.0 0.0 0.0 4.0 6.0 2.0 422.48
4 136.0 6 1001 59.0 145.0 7.0 141.0 75.0 306.0 411.0 0.0 6.0 32.0 266.0 38.0 2.0 23.0 211.0 367.0 6425.08

Serie temporelle Construction & Analyse:

In [11]:
%pylab inline

import warnings
warnings.filterwarnings('ignore')

import pandas as pd

import seaborn as sns
sns.set()


from statsmodels.tsa.stattools import adfuller


from statsmodels.tsa.stattools import acf, pacf
from copy import deepcopy


from datetime import datetime

from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.graph_objs as go
init_notebook_mode(connected=True)
Populating the interactive namespace from numpy and matplotlib
C:\Users\admin\Anaconda3\lib\site-packages\IPython\core\magics\pylab.py:160: UserWarning:

pylab import has clobbered these variables: ['random']
`%matplotlib` prevents importing * from pylab and numpy

ci dessu un set de nombreux fonction importante dont on aura recourt dans la premiere partie .

In [12]:
# Functions :

"""Plots a simple serie in PLOTLY."""
def jsplot(dates , values , mode = 'lines+markers'):

    data = [go.Scatter(
              x=dates,
              y=values,
              mode = mode)]

    iplot(data)
    
    
"""Plot multiple series in PLOTLY:"""
def jsplot_multiple(dates , values , mode = 'lines+markers'):

    data = []
    for col in values.columns:
        splot = go.Scatter(
                        x=dates,
                        y=values[col],
                        mode = mode,
                        name = str(col) )
        data.append(splot)

    iplot(data)
    
    
"""Function that test the stationarity of a Time series by
computing and plotting rolling statistics, and then by performing
An augmented Dickey Fuller test.""" 

def test_stationarity(timeseries , window = 50):
    #Determing rolling statistics
    rolmean = timeseries.rolling(window).mean()
    rolstd = timeseries.rolling(window).std()

    #Plot rolling statistics:
    fig = plt.figure(figsize=(12, 8))
    orig = plt.plot(timeseries,label='Original')
    mean = plt.plot(rolmean, color='red' , label='Rolling Mean')
    std = plt.plot(rolstd, label = 'Rolling Std')
    plt.legend(loc='best')
    plt.title('Rolling Mean & Standard Deviation')
    plt.show()
    
    #Perform Dickey-Fuller test:
    print('Results of Dickey-Fuller Test:')
    try:
        dftest = adfuller(timeseries.dropna(), autolag='AIC')
        dfoutput = pd.Series(dftest[0:4], index=['Test Statistic','p-value','#Lags Used','Number of Observations Used'])
        for key,value in dftest[4].items():
            dfoutput['Critical Value (%s)'%key] = value
        print(dfoutput) 
    except:
        print('test failed')
        

        
"""Performs Acp - Pacp Analysis on a time serie."""
def acp_pacp(timeseries , nlags = 30):
    lag_acf = acf(timeseries, nlags=nlags)
    lag_pacf = pacf(timeseries, nlags=nlags, method='ols')
    
    print('lag_acf')
    fig = plt.figure(figsize=(7 , 6))

    sns.barplot( np.arange(len(lag_acf)) , lag_acf , palette = 'GnBu_d')
    
    
    plt.axhline(y=0,linestyle='--',color='gray')
    plt.axhline(y=-1.96/np.sqrt(len(timeseries)),linestyle='--',color='gray')
    plt.axhline(y=1.96/np.sqrt(len(timeseries)),linestyle='--',color='gray')

    plt.show()
    print('lag_pacf')
    fig = plt.figure(figsize=(7, 6))

    sns.barplot( np.arange(len(lag_pacf)) , lag_pacf , palette = 'GnBu_d')

    plt.axhline(y=0,linestyle='--',color='gray')
    plt.axhline(y=-1.96/np.sqrt(len(timeseries)),linestyle='--',color='gray')
    plt.axhline(y=1.96/np.sqrt(len(timeseries)),linestyle='--',color='gray')

    plt.show()
In [13]:
caracs = pd.read_csv('caracteristics.csv' , encoding = 'latin-1') # Caracteristics of the accidents.
places = pd.read_csv('places.csv' ) # Places features.
users = pd.read_csv('users.csv' ) # Users involved in the accdient features.
vehicles = pd.read_csv('vehicles.csv') # Vehicles features.

caracs2017 = pd.read_csv('caracteristiques-2017.csv' , encoding = 'latin-1') # Caracteristics of the accidents.

on importe aussi tout les étés en france entre 2005 et 2017. ces informations sont valorisantes vue qu'elles affectes toujours le traffic et le comportement des conducteurs

In [14]:
holidays = pd.read_csv('holidays.csv') # Vehicles features.
In [15]:
holidays.head()
Out[15]:
ds holiday
0 2005-01-01 New year
1 2005-03-28 Easter Monday
2 2005-05-01 Labour Day
3 2005-05-05 Ascension Thursday
4 2005-05-08 Victory in Europe Day
In [16]:
caracs = pd.concat([caracs2017,caracs])
In [17]:
caracs.head()
Out[17]:
Num_Acc an mois jour hrmn lum agg int atm col com adr gps lat long dep
0 201700000001 17 1 11 1820 5 2 1 1.0 1.0 477.0 rue nationale M 5051326.0 292191 590
1 201700000002 17 2 13 1630 1 2 3 1.0 3.0 5.0 5 rue sonneville M 5053611.0 295314 590
2 201700000003 17 3 7 1150 1 2 9 1.0 5.0 52.0 rue Jules Guesde M 5052174.0 288786 590
3 201700000004 17 4 22 1300 1 2 1 1.0 6.0 5.0 46 rue Sonneville M 5053723.0 295700 590
4 201700000005 17 5 20 1230 1 2 1 1.0 2.0 11.0 Rue roger salengro M 5052999.0 293798 590
In [18]:
places.head()
Out[18]:
Num_Acc catr voie v1 v2 circ nbv pr pr1 vosp prof plan lartpc larrout surf infra situ env1
0 201600000001 3.0 39 NaN NaN 2.0 0.0 NaN NaN 0.0 1.0 3.0 0.0 0.0 1.0 0.0 1.0 0.0
1 201600000002 3.0 39 NaN NaN 1.0 0.0 NaN NaN 0.0 1.0 2.0 0.0 58.0 1.0 0.0 1.0 0.0
2 201600000003 3.0 1 NaN NaN 2.0 2.0 NaN NaN 0.0 1.0 3.0 0.0 68.0 2.0 0.0 3.0 99.0
3 201600000004 4.0 0 NaN NaN 2.0 0.0 NaN NaN 0.0 1.0 1.0 0.0 0.0 1.0 0.0 1.0 99.0
4 201600000005 4.0 0 NaN NaN 0.0 0.0 NaN NaN 0.0 0.0 1.0 0.0 0.0 1.0 0.0 1.0 3.0

Construction de la serie temporelle :

On construit la serie tomporelle en comptant les nombres des accident par jour en paris entre 2005 et 2017. et apres on visualise le resultat dans plotly .

In [35]:
dtsers = caracs.loc[(caracs.dep.isin([750])) , ['Num_Acc' , 'jour' , 'mois' , 'an']]

# zedna colom day feha feha y/m/d w dropina jour mois an
dtsers['day'] = pd.to_datetime((2000+dtsers.an)*10000+dtsers.mois*100+dtsers.jour,format='%Y%m%d')
dtsers.drop(['jour' , 'mois' , 'an'] , axis = 1 ,inplace = True)


dtsers = dtsers.groupby('day' , as_index = False).count()

# Dummy Variable Holiday
dtsers['isholiday'] = 0
dtsers.loc[dtsers.day.isin(holidays.ds) , 'isholiday'] = 1

# Week day and month
dtsers['weekday'] = dtsers.day.dt.weekday
dtsers['month'] = dtsers.day.dt.month
# Dummification
dtsers = pd.get_dummies(dtsers , columns = ['weekday' , 'month'])

print(' the 3 last years of the time series:')

#dtsers.day[3500]  bech traj3ek li 2014 08 02 w bech tarja3 b number daccdent li nfes el wa9t

jsplot(dtsers.day[3500:] , dtsers.Num_Acc[3500:] )
 the 3 last years of the time series:
Jul 2014Jan 2015Jul 2015Jan 2016Jul 2016Jan 2017Jul 2017Jan 2018010203040Export to plot.ly »
In [25]:
z=dtsers.head()
dtsers.head()
Out[25]:
day Num_Acc isholiday weekday_0 weekday_1 weekday_2 weekday_3 weekday_4 weekday_5 weekday_6 ... month_3 month_4 month_5 month_6 month_7 month_8 month_9 month_10 month_11 month_12
0 2005-01-01 9 1 0 0 0 0 0 1 0 ... 0 0 0 0 0 0 0 0 0 0
1 2005-01-02 10 0 0 0 0 0 0 0 1 ... 0 0 0 0 0 0 0 0 0 0
2 2005-01-03 9 0 1 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
3 2005-01-04 17 0 0 1 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
4 2005-01-05 28 0 0 0 1 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0

5 rows × 22 columns

In [24]:
z.to_csv('out.csv')

Les séries Temporelles sont stationnaires si elles n’ont pas d’effet de tendance ou de saisonnalité.

Il ne semble pas y avoir de tendance particulière dans la série Temporelle. Mais nous pouvons noter des modèles saisonniers qui seront d'une grande valeur pour notre modèle, ainsi qu'un grand nombre de pics que nous pouvons essayer d'expliquer pour mieux comprendre le problème. Voyons cela de plus près.

Analyse de la serie Temporelle :

Statistique

Commençons par calculer certaines statistiques telles que la moyenne et l'écart-type glissants, et utilisons un test statistique (Dickey-Fuler) pour déterminer si la série est stationnaire.

La stationnarité d'une série Temporelle est importante pour la modélisation. Certains modèles ne peuvent fonctionner qu'avec des séries temporelles stationnaires. C'est également un bon aperçu de la structure de la série chronologique: cette analyse nous aide à détecter les tendances, les ruptures structurelles et tout type de configuration anormale qui peut nous aider à mieux comprendre et à adapter nos modèles et à les généraliser davantage.

nous testons la saritéarité autour de la moyenne et de la variance

In [15]:
# Statistique :
test_stationarity(dtsers.Num_Acc , window = 30)
Results of Dickey-Fuller Test:
Test Statistic                -8.947931e+00
p-value                        8.883726e-15
#Lags Used                     3.200000e+01
Number of Observations Used    4.715000e+03
Critical Value (1%)           -3.431738e+00
Critical Value (5%)           -2.862153e+00
Critical Value (10%)          -2.567096e+00
dtype: float64

The p-value of the test indicates that the series is stationary. We don't notice any significant trend, but we can clearly see seasonal patterns.

Let's now look at the auto correlation plots:

la p-value des teste démontre que la serie est stationnaire .Nous ne remarquons aucune tendance significative, mais nous pouvons clairement voir les tendances saisonnières.

In [16]:
acp_pacp(dtsers.Num_Acc) # Nombre d'accident par jour
lag_acf
lag_pacf

Ces graphiques confirment qu'il existe une forte saisonnalité dans nos données. Nous pouvons clairement voir que nous avons ici une saisonnalité hebdomadaire, donc une tendance qui se répète chaque semaine. Ce type de modèle est précieux car il nous permettra d’améliorer nos prévisions en fonction de ce qui s’est passé la semaine dernière, par exemple. Nous pouvons également noter une forte corrélation avec ce qui s'est passé la veille.

Suivons plus de types de saisonnalité:

Saisonnalité:

Saisonnalité horaire

Ce type de saisonnalité ne sera d'aucune utilité pour notre modèle, mais il est bon de savoir si nous voulons construire un modèle horaire plutôt qu'un modèle quotidien. Nous additionnerons simplement le nombre d'accidents par heure après avoir distingué les accidents graves (mort ou blessures graves) du reste et verrons ce que nous pouvons trouver:

In [17]:
tempas = caracs.loc[caracs.dep == 750 , ['Num_Acc' , 'hrmn']]
tempas['hour'] = tempas['hrmn'].apply(lambda x:str(x).zfill(4)[:2])


grave_accs = users[users.grav.isin([2,3]) ].Num_Acc

tempas['gravity'] = 0
tempas.loc[tempas.Num_Acc.isin(grave_accs),'gravity'] = 1

# bech ta3mel dataset feha el  wa9t w el somme ta3 el gravity 
# (5thina ken acc 2 w acc 3 w7tina ken moucch grav =0 w ken grave = 1 w3malana par rapport ombre total des acc)
occs = tempas.drop('hrmn' , axis = 1).groupby('hour' , as_index = False).agg({'Num_Acc' : 'count' , 'gravity' : 'sum'})



trace1 = go.Area(
    r=list(occs.Num_Acc),
    t=list(occs.hour),
    name='Total Number of accidents',
    marker=dict(
        color='rgb(155, 236, 0)'
    )
)

trace2 = go.Area(
    r=list(occs.gravity),
    t=list(occs.hour),
    name='Grave accidents',
    marker=dict(
        color='rgb(158,154,200)'
    )
)

data = [trace1 , trace2]

layout = go.Layout(
    title='Repartition of accidents per Hour',
    autosize = False,
    width = 1000,
    height = 500,
    orientation=-90
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
' + '' + '' + '' + '' + '' + '' + '02,0004,0006,000' + '00061218' + '' + '' + 'Total Number of accidentsGrave accidentsc' + '' + 'Repartition of accidents per Hour' + '' + 'Export to plot.ly »

Nous pouvons clairement remarquer deux pointes, une à 09h00, le moment où les gens se rendent au travail, et une autre entre 17h00 et 18h00, au moment où les gens rentrent chez eux. Le nombre d'accidents diminue entre ces deux pics. Rien d'inhabituel, mais cela prouve qu'il existe une tendance.

Nous pouvons également constater qu’il ya peu d’accidents graves à Paris car il n’ya que des routes de ville.

Saisonnalité journalière

In [85]:
tempas = caracs.loc[caracs.dep == 750 ,['Num_Acc']]
tempas['date'] = pd.to_datetime((2000+caracs.an)*10000+caracs.mois*100+caracs.jour,format='%Y%m%d')
tempas['weekday'] = tempas['date'].dt.weekday.apply(lambda x:str(x).zfill(2))

tempas['gravity'] = 0
tempas.loc[tempas.Num_Acc.isin(grave_accs),'gravity'] = 1


occs = tempas.drop('date' , axis = 1).groupby('weekday' , as_index = False).agg({'Num_Acc' : 'count' , 'gravity' : 'sum'})



trace1 = go.Area(
    r=list(occs.Num_Acc),
    t=list(occs.weekday),
    name='Total Number of accidents',
    marker=dict(
        color='rgb(106,81,163)'
    )
)

trace2 = go.Area(
    r=list(occs.gravity),
    t=list(occs.weekday),
    name='Grave accidents',
    marker=dict(
        color='rgb(158,154,200)'
    )
)

data = [trace1 , trace2]

layout = go.Layout(
    title='Repartition of accidents per weekday',
    autosize = False,
    width = 1000,
    height = 500,
    orientation=-90
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
' + '' + '' + '' + '' + '' + '' + '05,00010,000' + '00020406' + '' + '' + 'Total Number of accidentsGrave accidentsc' + '' + 'Repartition of accidents per weekday' + '' + 'Export to plot.ly »
In [ ]:
occs

Même chose ici, nous pouvons clairement remarquer une tendance, où le nombre d'accidents diminue le vendredi et le dimanche et atteint son minimum le samedi. Les autres jours sont à peu près les mêmes (jours ouvrables).

Saisonnalité mensuelle

In [27]:
tempas = caracs.loc[caracs.dep == 750 ,['Num_Acc' , 'mois']]
tempas['mois'] = tempas['mois'].apply(lambda x:str(x).zfill(2))

tempas['gravity'] = 0
tempas.loc[tempas.Num_Acc.isin(grave_accs),'gravity'] = 1


occs = tempas.groupby('mois' , as_index = False).agg({'Num_Acc' : 'count' , 'gravity' : 'sum'})



trace1 = go.Area(
    r=list(occs.Num_Acc),
    t=list(occs.mois),
    name='Total Number of accidents',
    marker=dict(
        color='rgb(106,81,163)'
    )
)

trace2 = go.Area(
    r=list(occs.gravity),
    t=list(occs.mois),
    name='Grave accidents',
    marker=dict(
        color='rgb(158,154,200)'
    )
)

data = [trace1 , trace2]

layout = go.Layout(
    title='Repartition of accidents per Hour',
    autosize = False,
    width = 1000,
    height = 500,
    orientation=-90
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
' + '' + '' + '' + '' + '' + '' + '02,0004,0006,0008,000' + '01040710' + '' + '' + 'Total Number of accidentsGrave accidentsc' + '' + 'Repartition of accidents per Hour' + '' + 'Export to plot.ly »
In [ ]:
occs

Encore une fois, on peut voir un motif annuel dans la série chronologique, fortement lié au temps passé en vacances (août, décembre, ...).

En incorporant ces modèles dans nos modèles, nous pourrons faire de meilleures prévisions.

modelisation:

Pour noter nos modèles, nous allons utiliser cette fonction qui calcule un ensemble de statistiques significatives pour les prédictions que nous faisons. Nous allons tester notre modèle l'année dernière et voir comment il fonctionne.

La fonction ci-dessous calculera l'erreur moyenne, l'erreur absolue moyenne (MAE), l'erreur quadratique moyenne (RMSE), l'erreur moyenne en pourcentage (MPE), la corrélation entre la valeur vraie et l'erreur pour voir s'il reste des informations. . Il va également tracer la distribution de l'erreur et la prédiction par rapport à la valeur vraie en fonction du temps.

In [28]:
def evaluate(y_true , y_pred , dates):
    
    try:
        true_value , prediction = y_true.sum(axis = 1), y_pred.sum(axis=1).round()
    except:
        true_value , prediction = y_true, y_pred.round()
    
    print('Mean Absolute Error   :' , round(abs(true_value - prediction).mean() , 2)) 
    print('Root Mean Square Error:' , round(sqrt(((true_value - prediction)**2).mean()) , 2) )
    print('Mean Percentage Error :' , round((abs(true_value - prediction)/true_value).mean() , 2)  )
    
    error = pd.Series(true_value - prediction)
    
    #density plot :
    print('Error Density :')
    error.plot.density()
    plt.show()
    
    # mean of error and correlation :
    print('Mean Error                       :' , round(mean(error) , 2 ))
    print('True Value And error Correlation :' , round(np.corrcoef(error , true_value)[0 , 1] , 2))
    
    # plot :
    
    to_plot = pd.DataFrame({'target' : y_true.reshape(-1) , 'prediction' : y_pred.reshape(-1)})
    
    jsplot_multiple(dates , to_plot)

Modèle Naïf:

Avant d'aller plus loin, nous devons créer un modèle «naïf» qui représentera la performance minimale acceptable pour pouvoir comparer les modèles que nous allons construire. Ce modèle doit être le plus simple et le plus intuitif possible.

Puisque nous avons de fortes tendances saisonnières et aucune tendance, nous prendrons le nombre d'accidents l'année dernière dans la même journée la même semaine que la prévision pour cette année et verrons quelles performances nous obtiendrons:

on utilise 2015 pour predire 2016 :

In [29]:
# Naive Model :

new , old = (dtsers.loc[dtsers.day.dt.year == 2016 , ['day' , 'Num_Acc']].reset_index(drop = True) ,
             dtsers.loc[dtsers.day.dt.year == 2015 , ['day' , 'Num_Acc']].reset_index(drop = True)[:365])

old.columns = ['day' , 'old']

new['weekofyear'] , new['dayofweek'] = new.day.dt.weekofyear , new.day.dt.dayofweek
old['weekofyear'] , old['dayofweek'] = old.day.dt.weekofyear , old.day.dt.dayofweek

merged = new.merge(old , on = ['weekofyear' , 'dayofweek'])


evaluate(merged.Num_Acc.values , merged.old.values , dtsers.day[-365:])
Mean Absolute Error   : 5.07
Root Mean Square Error: 6.53
Mean Percentage Error : 0.33
Error Density :
Mean Error                       : 0.79
True Value And error Correlation : 0.52
Jan 2017Mar 2017May 2017Jul 2017Sep 2017Nov 2017Jan 2018010203040Export to plot.ly »
targetprediction

2016-2017 :

In [32]:
# Naive Model :

new , old = (dtsers.loc[dtsers.day.dt.year == 2017 , ['day' , 'Num_Acc']].reset_index(drop = True) ,
             dtsers.loc[dtsers.day.dt.year == 2016 , ['day' , 'Num_Acc']].reset_index(drop = True)[:365])

old.columns = ['day' , 'old']

new['weekofyear'] , new['dayofweek'] = new.day.dt.weekofyear , new.day.dt.dayofweek
old['weekofyear'] , old['dayofweek'] = old.day.dt.weekofyear , old.day.dt.dayofweek

merged = new.merge(old , on = ['weekofyear' , 'dayofweek'])


evaluate(merged.Num_Acc.values , merged.old.values , dtsers.day[-356:])
Mean Absolute Error   : 5.09
Root Mean Square Error: 6.6
Mean Percentage Error : 0.38
Error Density :
Mean Error                       : -1.4
True Value And error Correlation : 0.52
Jan 2017Mar 2017May 2017Jul 2017Sep 2017Nov 2017Jan 2018010203040Export to plot.ly »
targetprediction

Prophet:

Nous allons d'abord essayer la bibliothèque Prophet, créée par Facebook. Prophet est un outil de prévision développé par Facebook pour sa planification de la capacité. Il est très efficace lorsqu'il s'agit de problèmes à taille humaine. Il est basé sur des modèles additifs généralisés.

La bibliothèque elle-même est facilement utilisable, car le modèle se paramétrera lui-même pour la plupart. Il prend également directement les dates brutes et les vacances sans qu'il soit nécessaire de prétraiter ces variables.

Essayons ce modèle sur nos données.

In [33]:
from fbprophet import Prophet
In [34]:
#Initialisation of the model.
model = Prophet(holidays = holidays , yearly_seasonality=True , weekly_seasonality=True, daily_seasonality=False)

#train & test set.
histo , new = dtsers[dtsers.day.dt.year < 2016].reset_index(drop = True) , dtsers[dtsers.day.dt.year 
                                                                                  == 2016].reset_index(drop = True)

# We rename the columns before fitting the model to Prophet.
ncols = histo.columns.values
ncols[0] , ncols[1] = 'ds' , 'y'

histo.columns , new.columns = ncols , ncols

# We fit the model.
model.fit(histo)


# Prediction
ypred = model.predict(new)['yhat'].round()

# Evaluation
evaluate(new.y.values , ypred.values , dtsers.day[-365:])
Mean Absolute Error   : 3.86
Root Mean Square Error: 5.06
Mean Percentage Error : 0.25
Error Density :
Mean Error                       : 1.41
True Value And error Correlation : 0.63
Jan 2017Mar 2017May 2017Jul 2017Sep 2017Nov 2017Jan 2018010203040Export to plot.ly »
targetprediction

Nous pouvons constater une nette amélioration par rapport au modèle naïf. nous avons pu réduire l'erreur moyenne en pourcentage de 7% et nous avons également amélioré les autres mesures (de 38% à 29%)

In [3]:
# import the required libraries 

from plotly.offline import init_notebook_mode, iplot
import plotly.graph_objs as go
import numpy as np

import plotly.plotly as py
from plotly import tools
import pandas as pd
import string, os, random
import calendar
import numpy as np
globalcolors = ['092a35', 'a2738c', '645c84', '427996', '658525', '404b69', '0f4471', '0f4471', '0f4471', '0f4471']
init_notebook_mode(connected=True)
punc = string.punctuation
In [4]:
df1 = pd.read_csv('caracteristics.csv', low_memory = False, encoding = 'latin-1')
df2 = pd.read_csv('vehicles.csv', low_memory = False)
df3 = pd.read_csv('places.csv', low_memory = False)
df4 = pd.read_csv('users.csv', low_memory = False)
from functools import reduce
accidents = reduce(lambda left, right: pd.merge(left, right, on = "Num_Acc"), [df1, df2, df3, df4])
accidents = accidents.drop(['v2', 'v1', 'long', 'lat', 'pr1', 'pr', 'gps'], axis = 1)
In [6]:
accidents.columns.values
Out[6]:
array(['Num_Acc', 'an', 'mois', 'jour', 'hrmn', 'lum', 'agg', 'int',
       'atm', 'col', 'com', 'adr', 'dep', 'senc', 'catv', 'occutc', 'obs',
       'obsm', 'choc', 'manv', 'num_veh_x', 'catr', 'voie', 'circ', 'nbv',
       'vosp', 'prof', 'plan', 'lartpc', 'larrout', 'surf', 'infra',
       'situ', 'env1', 'place', 'catu', 'grav', 'sexe', 'trajet', 'secu',
       'locp', 'actp', 'etatp', 'an_nais', 'num_veh_y'], dtype=object)
In [6]:
accidents.an += 2000
dates = pd.to_datetime(accidents.an*10000+accidents.mois*100+accidents.jour,format='%Y%m%d')
accidents.an -= 2000
traces = []
for key, grp in dates.groupby(dates.dt.year):
    #print(grp)
    aggregated = grp.dt.month.value_counts().sort_index()
    x_values = aggregated.index.tolist()
    y_values = aggregated.values.tolist()
    x1,y1 = x_values, y_values
    x1 = [calendar.month_name[int(x)] for x in (x1)]


    

#x1, y1 = create_stack_bar_data('jour', accidents)
    trace1 = go.Scatter(x=x1, y=y1, opacity=0.75, line = dict(
        width = 1.5), name = str(key), marker = dict(color = np.random.randn(500)*key), mode = 'lines', 
                       text = str(key))
    layout = dict(height=400, title='Time Series of Accidents for each Year', legend=dict(orientation="h"));
    traces.append(trace1)
fig = go.Figure(data= traces, layout=layout)
iplot(fig, filename='stacked-bar')
JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecember15k20k25k30k35kExport to plot.ly »
200520062007200820092010201120122013201420152016Time Series of Accidents for each Year

Conclusion :

  • En utilisant la puissance de Prophet, nous avons déjà pu gagner beaucoup en performances par rapport au modèle Naïve.
  • nous constatons une répétition du nombre d'accidents qui se répète, c'est pourquoi nous avons utilisé l'an dernier pour prédire l'année suivante
  • Une forte augmentation est observée aux mois de juin, juillet, septembre et octobre.
  • Des baisses marquées sont observées en février et août.
  • En décembre 2006, le nombre d’accidents est le plus élevé, avec 36 648 personnes.
  • Février 2013 a le plus faible nombre d'accidents avec 15 605.
  • Le nombre d'accidents en France a régulièrement diminué de 2005 à 2013, mais une tendance à la hausse est observée de 2013 à 2016.
  • Dans cet ensemble de données, 2005 a enregistré le plus grand nombre d'accidents avec 374561.

Exploration basée sur les routes où des accidents sont survenus

In [11]:
# function to aggregate and return keys and values
def create_stack_bar_data(col, df):
    aggregated = df[col].value_counts().sort_index()
    x_values = aggregated.index.tolist()
    y_values = aggregated.values.tolist()
    return x_values, y_values

x1, y1 = create_stack_bar_data('an', accidents)

for i in range(len(x1)):
    x1[i] += 2000
In [13]:
x1, y1 = create_stack_bar_data('catr', accidents)
x1 = ['Highway', 'National Road', 'Departmental Road', 'Communal Way', 'Off-Public Network', 'Parking Lot', 'Other']
trace1 = go.Bar(x=x1, y=y1, opacity=0.75, name="Category")

x2, y2 = create_stack_bar_data('circ', accidents)
x2 = ['Unknown','One Way', 'Bidirectional', 'Separated Carriageways', 'Variable Assignment Channels']
trace2 = go.Bar(x = x2, y = y2, opacity = 0.75, name = "Traffic Flow")

x3, y3 = create_stack_bar_data('prof', accidents)
x3 = ['Unknown', 'Dish','Slope', 'Hill-Top', 'Hill-Bottom']
trace3 = go.Bar(x = x3, y = y3, opacity = 0.75, name = "Road Gradient")


fig = tools.make_subplots(rows = 3, cols = 1)

fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 2, 1)
fig.append_trace(trace3, 3, 1)
layout = dict(height=900, title='Accidents by Type of Road');
fig.layout.update(layout)
#fig['layout'].update(height=800,title='Accidents by Type of Road')
iplot(fig, filename='stacked-bar')
This is the format of your plot grid:
[ (1,1) x1,y1 ]
[ (2,1) x2,y2 ]
[ (3,1) x3,y3 ]

HighwayNational RoadDepartmental RoadCommunal WayOff-Public NetworkParking LotOther00.5M1M1.5MUnknownOne WayBidirectionalSeparated CarriagewaysVariable Assignment Channels00.5M1M1.5M2MUnknownDishSlopeHill-TopHill-Bottom00.5M1M1.5M2M2.5MExport to plot.ly »
CategoryTraffic FlowRoad GradientAccidents by Type of Road
  • Les voies communales et les routes départementales sont les plus risquées avec 1,6 million et 1,1 million d'accidents chacune.
  • Les routes bidirectionnelles sont de loin les plus risquées avec plus de 2,1 millions d'accidents
In [15]:
keydict = {1:'Highway', 2:'National Road', 3:'Departmental Road', 4:'Communal Way', 5:'Off-Public Network', 6:'Parking Lot', 9:'Other'}
roadtype = accidents[['catr','circ']]
traces = []
for key, grp in roadtype.groupby(roadtype.catr):
    aggregated = grp.circ.value_counts().sort_index()
    x_values = aggregated.index.tolist()
    y_values = aggregated.values.tolist()
    x1,y1 = x_values, y_values
    x1 = ['Unknown','One Way', 'Bidirectional', 'Separated Carriageways', 'Variable Assignment Channels']


    

#x1, y1 = create_stack_bar_data('jour', accidents)
    trace1 = go.Bar(x=x1, y=y1, opacity=0.75, name = keydict[key])
    layout = dict(height=400, title='Distribution of Accidents based on Type of Road', legend=dict(orientation="h"));
    traces.append(trace1)
fig = go.Figure(data= traces, layout=layout)
iplot(fig)
UnknownOne WayBidirectionalSeparated CarriagewaysVariable Assignment Channels00.2M0.4M0.6M0.8M1MExport to plot.ly »
HighwayNational RoadDepartmental RoadCommunal WayOff-Public NetworkParking LotOtherDistribution of Accidents based on Type of Road

Répartition des personnes impliquées dans des accidents par âge

In [18]:
ageusers = accidents[['an_nais', 'catu']]
ageusers['age'] = 2016 - ageusers.an_nais

keydict = {1:'Driver', 2:'Passenger', 3:'Pedestrian', 4:'Pedestrian in Motion'}
traces = []
for key, grp in ageusers.groupby(ageusers.catu):
    if(key < 4):
    #aggregated = grp.an_nais.value_counts().sort_index()
        x1 = grp.age.values
    #y_values = aggregated.values.tolist()
    #x1,y1 = x_values, y_values
    #x1 = ['Driver','Passenger', 'Pedestrian', 'Pedestrian in Motion']


    
    
#x1, y1 = create_stack_bar_data('jour', accidents)
        trace1 = go.Histogram(x=x1, opacity=0.5, name = keydict[key])
        layout = dict(height=400, title='Distribution of People involved in Accidents by Age', 
                  legend=dict(orientation="h"), barmode = 'overlay');
        traces.append(trace1)
fig = go.Figure(data= traces, layout=layout)
iplot(fig)
C:\Users\admin\Anaconda3\lib\site-packages\ipykernel_launcher.py:2: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

020406080100120020k40k60k80kExport to plot.ly »
DriverPassengerPedestrianDistribution of People involved in Accidents by Age
  • la plupart des conducteurs responsables des accidents ont entre 20 et 41 ans
  • la destitution des pedestrain blessés est uniforme dans tous les domaines
  • L'âge n'a pas d'importance, mais les conducteurs sont plus âgés, nous pouvons supposer qu'ils auront plus de risques d'accident.

le profil de l'itinéraire le plus propice aux accidents:

  • route communale ou départementale
  • bidirectionnel
  • promenade de plat

le profil des routes les plus sûres sont:

  • autoroute ou route nationale
  • pente
  • voies séparées

Quel était l'équipement de sécurité utilisé par les personnes impliquées?

L'effet de l'équipement de sécurité sur la fatalité de l'accident:

In [22]:
safety = accidents[['secu', 'grav']]
safety = safety.dropna()
safety['equipment'] = (safety.secu/10).astype(int)
safety.secu = (safety.secu - safety.equipment*10).astype(int)


x1, y1 = create_stack_bar_data('equipment', safety)
x1 = ['Belt', 'Helmet', "Children's Device", 'Reflective Equipment', "Other"]
trace1 = go.Bar(x=x1, y=y1, opacity=0.75)
layout = dict(height=400, title='Distribution of Safety Equipment', legend=dict(orientation="h") );

keydict = {1:'Unscathed', 2:'Killed', 3: 'Hospitalized', 4: 'Light Injury'}
traces = []
for key, grp in safety.groupby(safety.grav):
    if (key != 0):
        count = safety.secu.count()
        #print(count)
        aggregated = (grp.secu.value_counts()).sort_index()
        x_values = aggregated.index.tolist()
        y_values = (aggregated.values/safety.secu.value_counts().sort_index().values*100).tolist()
        x1,y1 = x_values[1:], y_values[1:]
        x1 = ['Equipment Present','Equipment Absent', 'Not Determined']


    

#x1, y1 = create_stack_bar_data('jour', accidents)
        trace1 = go.Bar(x=x1, y=y1, opacity=0.75, name = keydict[key])
        layout = dict(height=400, title='Relationship between Safety Equipment and Severity of Accident', 
                      legend=dict(orientation="h"), barmode = 'stack', yaxis = dict(title = 'Percentage'),
                      xaxis = dict(title = 'Safety Equipment'));
        traces.append(trace1)
fig = go.Figure(data= traces, layout=layout)
iplot(fig)
Equipment PresentEquipment AbsentNot Determined020406080100Export to plot.ly »
Light InjuryHospitalizedKilledUnscathedRelationship between Safety Equipment and Severity of AccidentSafety EquipmentPercentage
  • 1.9% of the people were killed and 17.8% were hospitalized if Safety Equipment was used.
  • 10.7% of the people were killed and 35.8% were hospitalized if Safety Equipment was not used.
In [1]:
import plotly.plotly as py
import plotly.graph_objs as go
import dash
import dash_core_components as dcc
import dash_html_components as html

import pandas as pd

df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv")
In [2]:
df.head()
Out[2]:
Date AAPL.Open AAPL.High AAPL.Low AAPL.Close AAPL.Volume AAPL.Adjusted dn mavg up direction
0 2015-02-17 127.489998 128.880005 126.919998 127.830002 63152400 122.905254 106.741052 117.927667 129.114281 Increasing
1 2015-02-18 127.629997 128.779999 127.449997 128.720001 44891700 123.760965 107.842423 118.940333 130.038244 Increasing
2 2015-02-19 128.479996 129.029999 128.330002 128.449997 37362400 123.501363 108.894245 119.889167 130.884089 Decreasing
3 2015-02-20 128.619995 129.500000 128.050003 129.500000 48948400 124.510914 109.785449 120.763500 131.741551 Increasing
4 2015-02-23 130.020004 133.000000 129.660004 133.000000 70974100 127.876074 110.372516 121.720167 133.067817 Increasing
In [75]:
import pandas as pd
import numpy as np
In [76]:
data = pd.read_csv("C:\\Users\\Aymen\\Desktop\\DS_Data\\Aggregation.csv")
In [77]:
pd.set_option('display.max_columns', 500)
data.head()
Out[77]:
Unnamed: 0 NomCommune an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3 nb_acc_catu4 nb_acc_atm2 nb_acc_atm3 nb_acc_atm4 nb_acc_atm5 nb_acc_atm6 nb_acc_atm7 nb_acc_atm8 nb_acc_atm9 nb_acc_prof1 nb_acc_prof2 nb_acc_prof3 nb_acc_prof4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4
0 0 FREIGNE 5 6 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 6.0 0.0 2.0 4.0
1 1 PRANZAC 5 3 2.0 1.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 2.0 0.0
2 2 LONGEVILLE-LES-SAINT-AVOLD 5 32 0.0 18.0 0.0 1.0 20.0 6.0 5.0 0.0 0.0 0.0 6.0 1.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 4.0 0.0 5.0 23.0 0.0 0.0 0.0 6.0 19.0
3 3 BEAUREPAIRE-EN-BRESSE 5 6 0.0 6.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0
4 4 CHALLES-LA-MONTAGNE 5 10 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 6.0 0.0 0.0 0.0 0.0 8.0
In [15]:
data_copy = data
In [78]:
from scipy import stats
import random
#df.isna().any()
while data.isna().any().any()==True:
    for i in data.columns:
        data[i] = data[i].fillna(random.choice(data[i]))

On passe maintenant a la division de notre dataset en 2 partie train et test

In [79]:
X = data.iloc[:, [2, 4, 5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]].values
y = data.iloc[:, 3].values
In [80]:
#np.isnan(X)
np.where(np.isnan(X))
np.nan_to_num(X)
Out[80]:
array([[ 5.,  0.,  0., ...,  0.,  0.,  0.],
       [ 5.,  2.,  1., ...,  0.,  0.,  0.],
       [ 5.,  0., 18., ...,  6.,  0.,  0.],
       ...,
       [17.,  0.,  1., ...,  1.,  0.,  0.],
       [17.,  6., 10., ...,  4.,  0.,  0.],
       [17.,  8., 16., ..., 61.,  6.,  1.]])
In [81]:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
X_train
Out[81]:
array([[12.,  0.,  0., ...,  0.,  0.,  0.],
       [13.,  0.,  0., ...,  0.,  0.,  0.],
       [ 7.,  0.,  4., ...,  0.,  0.,  0.],
       ...,
       [16.,  0.,  0., ...,  1.,  0.,  0.],
       [ 9.,  5.,  0., ...,  0.,  0.,  0.],
       [ 6.,  0.,  1., ...,  0.,  0.,  0.]])
In [82]:
np.isnan(X_test)
Out[82]:
array([[False, False, False, ..., False, False, False],
       [False, False, False, ..., False, False, False],
       [False, False, False, ..., False, False, False],
       ...,
       [False, False, False, ..., False, False, False],
       [False, False, False, ..., False, False, False],
       [False, False, False, ..., False, False, False]])
In [83]:
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
X_train
Out[83]:
array([[ 0.33380935, -0.20365565, -0.29570681, ..., -0.19041158,
        -0.15756695, -0.04315932],
       [ 0.59401441, -0.20365565, -0.29570681, ..., -0.19041158,
        -0.15756695, -0.04315932],
       [-0.96721593, -0.20365565,  0.31125459, ..., -0.19041158,
        -0.15756695, -0.04315932],
       ...,
       [ 1.37462957, -0.20365565, -0.29570681, ..., -0.10990558,
        -0.15756695, -0.04315932],
       [-0.44680582,  0.5547712 , -0.29570681, ..., -0.19041158,
        -0.15756695, -0.04315932],
       [-1.22742099, -0.20365565, -0.14396646, ..., -0.19041158,
        -0.15756695, -0.04315932]])
In [84]:
y_test.shape
Out[84]:
(29060,)

Linear regression

In [85]:
from sklearn.linear_model import LinearRegression
model_lr =  LinearRegression()
model_lr.fit(X_train, y_train)
Out[85]:
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
In [86]:
model_lr.coef_
Out[86]:
array([ 0.29451583,  4.30852098,  3.14311102,  1.97147241, 11.20097172,
        6.13798443,  9.38206508, 48.23531709,  0.32339258,  0.32140958,
        5.30478638, 33.32871038,  6.27796935,  0.49548193,  4.82778401,
        1.04919496,  0.65963065])
In [87]:
model_lr.intercept_
Out[87]:
23.117802420915897

NbrACC = 363.310 + 1.492 com + 2.799 an + 8.693 nb_acc_lum2+0.102 nb_acc_lum3 + nb_acc_lum4 2.407 + nb_acc_lum5 7.581 + nb_acc_catr2 9.193 + nb_acc_catr3 17.05 + nb_acc_catr4 88.24 - nb_acc_catr51.065 + nb_acc_catr6 0.1264 + nb_acc_catr9 2.348 + nb_acc_catu2 121.7 + nb_acc_catu3 19.46 + nb_acc_catu4 *5.958

In [101]:
y_pred = model_lr.predict(X_test)
In [102]:
resultModel = pd.DataFrame(y_test)
resultModel['predicted'] = y_pred
In [103]:
resultModel.head(10)
Out[103]:
0 predicted
0 15 7.880458
1 13 15.699881
2 4 8.945952
3 12 19.081803
4 1 0.015537
5 1 -0.367635
6 8 13.722600
7 8 10.996448
8 12 6.739655
9 51 62.555191
In [104]:
np.sum(( resultModel.iloc[:, 0].values - resultModel.iloc[:, 1].values)*( resultModel.iloc[:, 0].values - resultModel.iloc[:, 1].values))
Out[104]:
4480403.751877026
In [135]:
import matplotlib.pyplot as plt
#plt.scatter(X_train, y_train, color= 'red')
plt.plot(y_test, y_pred, color = 'blue')
plt.show()

2 éme modele de regression avec random forest

In [93]:
from sklearn.ensemble import RandomForestRegressor
reg_rf = RandomForestRegressor()
reg_rf.fit(X_train, y_train)
Out[93]:
RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,
           max_features='auto', max_leaf_nodes=None,
           min_impurity_decrease=0.0, min_impurity_split=None,
           min_samples_leaf=1, min_samples_split=2,
           min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1,
           oob_score=False, random_state=None, verbose=0, warm_start=False)
In [95]:
y_predRF = reg_rf.predict(X_test)
In [96]:
resultModel['predicted_RF'] = y_predRF
In [97]:
resultModel.head(10)
Out[97]:
0 predicted predicted_RF
0 15 7.880458 11.800000
1 13 15.699881 13.000000
2 4 8.945952 4.000000
3 12 19.081803 12.400000
4 1 0.015537 1.018320
5 1 -0.367635 1.032381
6 8 13.722600 8.000000
7 8 10.996448 8.000000
8 12 6.739655 12.500000
9 51 62.555191 51.800000
In [98]:
np.sum(( resultModel.iloc[:, 0].values - resultModel.iloc[:, 2].values)*( resultModel.iloc[:, 0].values - resultModel.iloc[:, 2].values))
Out[98]:
5181453.645152277
In [99]:
np.sum(( resultModel.iloc[:, 0].values - resultModel.iloc[:, 1].values)*( resultModel.iloc[:, 0].values - resultModel.iloc[:, 1].values))
Out[99]:
4480403.751877026

On remarque que la somme des erreurs du premier modele (linear regression) est plus faible que la somme des erreurs du deuxieme modele (random forest) donc on peut dire que linear modele est meilleur que random forest pour la prediction du nombre des accidents par commune.

On passe maintenant a la prediction de la gravite des accidents en se trainant notre modele sur les données des années entre 2005 et 2016 et predir la gravite des accident en 2017

Creation d'un modele qui permet de predir la gravité des accidents par commune

A l'aide d'une formule qui permet de calculer la gravité des accidents par commune : gravité = 100 nbr de personnes tués + 10.8 nbr de personnes hospitalisés + 0.44 * nbr de personnes blessés légérement

Ajout de la colonne qui contient le score de la gravites

In [17]:
garv_score= data.nb_acc_grav2*100+data.nb_acc_grav3*10.8+data.nb_acc_grav4*0.44
data['Grav_Score'] = garv_score
data.head(10)
Out[17]:
Unnamed: 0 NomCommune an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3 nb_acc_catu4 nb_acc_atm2 nb_acc_atm3 nb_acc_atm4 nb_acc_atm5 nb_acc_atm6 nb_acc_atm7 nb_acc_atm8 nb_acc_atm9 nb_acc_prof1 nb_acc_prof2 nb_acc_prof3 nb_acc_prof4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4 Grav_Score
0 0 FREIGNE 5 6 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 6.0 0.0 2.0 4.0 23.36
1 1 PRANZAC 5 3 2.0 1.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 2.0 0.0 21.60
2 2 LONGEVILLE-LES-SAINT-AVOLD 5 32 0.0 18.0 0.0 1.0 20.0 6.0 5.0 0.0 0.0 0.0 6.0 1.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 4.0 0.0 5.0 23.0 0.0 0.0 0.0 6.0 19.0 73.16
3 3 BEAUREPAIRE-EN-BRESSE 5 6 0.0 6.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.88
4 4 CHALLES-LA-MONTAGNE 5 10 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 6.0 0.0 0.0 0.0 0.0 8.0 3.52
5 5 LA CHARITE-SUR-LOIRE 5 18 0.0 1.0 0.0 2.0 13.0 4.0 0.0 0.0 0.0 1.0 9.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 17.0 1.0 0.0 0.0 0.0 3.0 3.0 33.72
6 6 LINSELLES 5 24 0.0 0.0 0.0 2.0 0.0 14.0 2.0 4.0 4.0 0.0 2.0 1.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 24.0 0.0 0.0 0.0 0.0 7.0 10.0 80.00
7 7 SURESNES 5 315 23.0 2.0 0.0 73.0 4.0 217.0 94.0 0.0 0.0 0.0 43.0 16.0 0.0 38.0 9.0 7.0 0.0 0.0 0.0 0.0 0.0 199.0 72.0 21.0 9.0 0.0 24.0 140.0 320.80
8 8 LE BLANC-MESNIL 5 246 1.0 0.0 0.0 86.0 20.0 38.0 184.0 2.0 2.0 0.0 34.0 12.0 0.0 41.0 1.0 6.0 1.0 0.0 0.0 6.0 0.0 222.0 10.0 0.0 0.0 0.0 68.0 65.0 763.00
9 9 NOGUERES 5 1 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 10.80
In [18]:
data.describe()
Out[18]:
Unnamed: 0 an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3 nb_acc_catu4 nb_acc_atm2 nb_acc_atm3 nb_acc_atm4 nb_acc_atm5 nb_acc_atm6 nb_acc_atm7 nb_acc_atm8 nb_acc_atm9 nb_acc_prof1 nb_acc_prof2 nb_acc_prof3 nb_acc_prof4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4 Grav_Score
count 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.000000 145297.00000
mean 72648.000000 10.711866 23.166610 1.339064 1.940315 0.175275 3.406657 2.231808 7.886295 9.717179 0.028659 0.109376 0.386574 4.183975 1.017585 0.022485 2.395679 0.520086 0.185634 0.282256 0.053181 0.242985 0.810540 0.172233 17.536012 3.129927 0.466479 0.325492 0.561016 4.489329 7.916908 108.06983
std 41943.775369 3.846001 110.672351 6.514312 6.533076 1.601903 26.568019 13.603656 19.813582 86.648989 0.460075 0.885468 12.714076 17.004294 6.303151 0.235082 12.700141 3.275382 4.059776 15.813578 0.792665 2.697851 9.703389 1.789550 91.699282 18.337858 3.321086 3.391479 1.440505 12.267229 49.409498 243.32516
min 0.000000 5.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.44000
25% 36324.000000 7.000000 3.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 11.24000
50% 72648.000000 11.000000 6.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 0.000000 0.000000 2.000000 0.000000 32.40000
75% 108972.000000 14.000000 12.000000 0.000000 1.000000 0.000000 0.000000 0.000000 8.000000 1.000000 0.000000 0.000000 0.000000 4.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 9.000000 1.000000 0.000000 0.000000 1.000000 4.000000 3.000000 110.80000
max 145296.000000 17.000000 7440.000000 679.000000 448.000000 91.000000 3325.000000 1331.000000 2210.000000 6238.000000 64.000000 64.000000 3410.000000 1851.000000 350.000000 21.000000 595.000000 324.000000 1120.000000 5084.000000 72.000000 846.000000 3294.000000 183.000000 6186.000000 3294.000000 396.000000 915.000000 175.000000 778.000000 3500.000000 19668.80000
In [20]:
data["Gravity acc"] = 0
Out[20]:
Unnamed: 0 NomCommune an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3 nb_acc_catu4 nb_acc_atm2 nb_acc_atm3 nb_acc_atm4 nb_acc_atm5 nb_acc_atm6 nb_acc_atm7 nb_acc_atm8 nb_acc_atm9 nb_acc_prof1 nb_acc_prof2 nb_acc_prof3 nb_acc_prof4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4 Grav_Score Gravity acc
0 0 FREIGNE 5 6 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 6.0 0.0 2.0 4.0 23.36 0
1 1 PRANZAC 5 3 2.0 1.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 2.0 0.0 21.60 0
2 2 LONGEVILLE-LES-SAINT-AVOLD 5 32 0.0 18.0 0.0 1.0 20.0 6.0 5.0 0.0 0.0 0.0 6.0 1.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 4.0 0.0 5.0 23.0 0.0 0.0 0.0 6.0 19.0 73.16 0
3 3 BEAUREPAIRE-EN-BRESSE 5 6 0.0 6.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.88 0
4 4 CHALLES-LA-MONTAGNE 5 10 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 6.0 0.0 0.0 0.0 0.0 8.0 3.52 0

D'apres le score de la gravite on a ajouté une autre colonne qualitative qui va etre notre variable cible qui contient la degres de gravite des accident (pas grave, moyennement grave, grave, tres grave)

In [ ]:
for j in range(0, len(data)):
        if( data['Grav_Score'][j]  <= 11):
            data['Gravity acc'][j] = "Pas Grave"
            print(data["Grav_Score"][j])
        elif (data['Grav_Score'][j] > 11 and data['Grav_Score'][j] <= 32):
            data['Gravity acc'][j] = "Moyennement Grave"
        elif(data['Grav_Score'][j] > 32 and data['Grav_Score'][j] <= 110):
            data['Gravity acc'][j] = "Grave"
        else:
            data['Gravity acc'][j] = "Tres Grave"
data.head(10)
In [22]:
data.head()
Out[22]:
Unnamed: 0 NomCommune an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3 nb_acc_catu4 nb_acc_atm2 nb_acc_atm3 nb_acc_atm4 nb_acc_atm5 nb_acc_atm6 nb_acc_atm7 nb_acc_atm8 nb_acc_atm9 nb_acc_prof1 nb_acc_prof2 nb_acc_prof3 nb_acc_prof4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4 Grav_Score Gravity acc
0 0 FREIGNE 5 6 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 6.0 0.0 2.0 4.0 23.36 Moyennement Grave
1 1 PRANZAC 5 3 2.0 1.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 2.0 0.0 21.60 Moyennement Grave
2 2 LONGEVILLE-LES-SAINT-AVOLD 5 32 0.0 18.0 0.0 1.0 20.0 6.0 5.0 0.0 0.0 0.0 6.0 1.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 4.0 0.0 5.0 23.0 0.0 0.0 0.0 6.0 19.0 73.16 Grave
3 3 BEAUREPAIRE-EN-BRESSE 5 6 0.0 6.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.88 Pas Grave
4 4 CHALLES-LA-MONTAGNE 5 10 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 6.0 0.0 0.0 0.0 0.0 8.0 3.52 Pas Grave
In [1]:
import pandas as pd
In [24]:
data.to_csv('data2.csv',sep=';')

Chargement de la dataset et suppression des variables qualitatives et non significatives pour le modele qu'on va appliquer telques (numero communes,non cummone, codes departements,sexe...)

In [111]:
data=pd.read_csv('data2.csv',sep=';')
data.drop(['Unnamed: 0'], axis=1, inplace=True)
data.drop(['Unnamed: 0.1'], axis=1, inplace=True)
data.head()
Out[111]:
NomCommune an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3 nb_acc_catu4 nb_acc_atm2 nb_acc_atm3 nb_acc_atm4 nb_acc_atm5 nb_acc_atm6 nb_acc_atm7 nb_acc_atm8 nb_acc_atm9 nb_acc_prof1 nb_acc_prof2 nb_acc_prof3 nb_acc_prof4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4 Grav_Score Gravity acc
0 FREIGNE 5 6 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 6.0 0.0 2.0 4.0 23.36 Moyennement Grave
1 PRANZAC 5 3 2.0 1.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 2.0 0.0 21.60 Moyennement Grave
2 LONGEVILLE-LES-SAINT-AVOLD 5 32 0.0 18.0 0.0 1.0 20.0 6.0 5.0 0.0 0.0 0.0 6.0 1.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 4.0 0.0 5.0 23.0 0.0 0.0 0.0 6.0 19.0 73.16 Grave
3 BEAUREPAIRE-EN-BRESSE 5 6 0.0 6.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.88 Pas Grave
4 CHALLES-LA-MONTAGNE 5 10 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 6.0 0.0 0.0 0.0 0.0 8.0 3.52 Pas Grave

On passe a l'application des moedeles.

Logistic regression

In [112]:
X = data.iloc[:, 1:-2].values
y = data.iloc[:, -1].values
In [113]:
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
y = encoder.fit_transform(y)
In [114]:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)

On passe au centrage reduction avant d'appliquer le modele

In [115]:
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
In [116]:
from sklearn.linear_model import LogisticRegression
model_log = LogisticRegression()
model_log.fit(X_train, y_train)
Out[116]:
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
          penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False)
In [118]:
y_pred = model_log.predict(X_test)
y_pred == y_test
Out[118]:
array([ True,  True, False, ...,  True,  True,  True])
In [119]:
sum(y_pred == y_test)
Out[119]:
27151

Le modele a predit plus que 1900 lignes fausse.

In [120]:
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_pred, y_test)
cm
Out[120]:
array([[7247,  434,    6,   23],
       [ 359, 5785,   29,    0],
       [   0,  914, 6740,    0],
       [ 144,    0,    0, 7379]], dtype=int64)
In [121]:
from sklearn.metrics import classification_report
print(classification_report(y_test,y_pred))
             precision    recall  f1-score   support

          0       0.94      0.94      0.94      7750
          1       0.94      0.81      0.87      7133
          2       0.88      0.99      0.93      6775
          3       0.98      1.00      0.99      7402

avg / total       0.94      0.93      0.93     29060

Ce modele de regression logistique a donné des bonnes resultats de prediction sur ce jeu de donnée

On passe a la creation d'un autre modele et puis les comparés pour pouvoir tirer le meilleur modeles

Random forest

In [22]:
from sklearn.ensemble import RandomForestClassifier
model_rf = RandomForestClassifier(n_estimators=500, criterion="gini")
C:\Users\Aymen\Anaconda3\lib\site-packages\sklearn\ensemble\weight_boosting.py:29: DeprecationWarning: numpy.core.umath_tests is an internal NumPy module and should not be imported. It will be removed in a future NumPy release.
  from numpy.core.umath_tests import inner1d
In [23]:
model_rf.fit(X_train, y_train)
Out[23]:
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
            max_depth=None, max_features='auto', max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, n_estimators=500, n_jobs=1,
            oob_score=False, random_state=None, verbose=0,
            warm_start=False)
In [24]:
y_pred2 = model_rf.predict(X_test)
sum(y_pred2 == y_test)
Out[24]:
29030
In [25]:
cm = confusion_matrix(y_pred2, y_test)
cm
Out[25]:
array([[7736,    2,    0,    8],
       [   4, 7128,    3,    0],
       [   0,    3, 6772,    0],
       [  10,    0,    0, 7394]], dtype=int64)
In [26]:
print(classification_report(y_test,y_pred2))
             precision    recall  f1-score   support

          0       1.00      1.00      1.00      7750
          1       1.00      1.00      1.00      7133
          2       1.00      1.00      1.00      6775
          3       1.00      1.00      1.00      7402

avg / total       1.00      1.00      1.00     29060

Le modele de random forest a donné des resultats meilleur que le modele precedent

Comparaison entre les modeles

In [122]:
models = pd.DataFrame(data = {"Classifier name" : ["Logistic regression","Random forest"],
                              "Classifier" : [model_log, model_rf]})
In [132]:
from sklearn import metrics
import matplotlib.pyplot as plt
for i,j in models.iterrows():
    m = j["Classifier"]
    m.fit(X_train, y_train)
    y_pred = m.predict(X_test)
    cm = confusion_matrix(y_test, y_pred)
    auc = metrics.roc_auc_score(y_test == 3, y_pred)
    print(j["Classifier name"])
    print("AUC = ", auc)
    print(cm)
    fpr, tpr, thresholds = metrics.roc_curve(y_test, y_pred, pos_label=3)
    plt.plot(fpr, tpr, label='%s ROC (area = %0.2f)' % (j['Classifier name'], auc))
    
plt.plot([0, 1], [0, 1])
plt.legend(loc = "lower right")
plt.show();
Logistic regression
AUC =  0.9941300808977386
[[7247  359    0  144]
 [ 434 5785  914    0]
 [   6   29 6740    0]
 [  23    0    0 7379]]
Random forest
AUC =  0.9987477085070513
[[7735    4    0   11]
 [   4 7127    2    0]
 [   0    3 6772    0]
 [   9    0    0 7393]]
L'idée dans cette partie est de supprimer des colonnes avec lesquels on a fait le calcule de score de gravite et appliquons nos modeles pour tester a nouveau.
In [133]:
data2 = data
In [134]:
data2.head()
Out[134]:
NomCommune an nb_acc_tot nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3 nb_acc_catu4 nb_acc_atm2 nb_acc_atm3 nb_acc_atm4 nb_acc_atm5 nb_acc_atm6 nb_acc_atm7 nb_acc_atm8 nb_acc_atm9 nb_acc_prof1 nb_acc_prof2 nb_acc_prof3 nb_acc_prof4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4 Grav_Score Gravity acc
0 FREIGNE 5 6 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 6.0 0.0 2.0 4.0 23.36 Moyennement Grave
1 PRANZAC 5 3 2.0 1.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 2.0 0.0 21.60 Moyennement Grave
2 LONGEVILLE-LES-SAINT-AVOLD 5 32 0.0 18.0 0.0 1.0 20.0 6.0 5.0 0.0 0.0 0.0 6.0 1.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 4.0 0.0 5.0 23.0 0.0 0.0 0.0 6.0 19.0 73.16 Grave
3 BEAUREPAIRE-EN-BRESSE 5 6 0.0 6.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 2.0 0.88 Pas Grave
4 CHALLES-LA-MONTAGNE 5 10 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 6.0 0.0 0.0 0.0 0.0 8.0 3.52 Pas Grave

Suppression des variables

In [135]:
data2.drop(['nb_acc_tot', "Grav_Score", "nb_acc_catu2", "nb_acc_catu3", "nb_acc_catu4", "nb_acc_grav4", "nb_acc_grav2", "nb_acc_grav3"], axis=1, inplace=True)
data2.head()
Out[135]:
NomCommune an nb_acc_lum2 nb_acc_lum3 nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4 nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_atm2 nb_acc_atm3 nb_acc_atm4 nb_acc_atm5 nb_acc_atm6 nb_acc_atm7 nb_acc_atm8 nb_acc_atm9 nb_acc_prof1 nb_acc_prof2 nb_acc_prof3 nb_acc_prof4 Gravity acc
0 FREIGNE 5 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 6.0 Moyennement Grave
1 PRANZAC 5 2.0 1.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 Moyennement Grave
2 LONGEVILLE-LES-SAINT-AVOLD 5 0.0 18.0 0.0 1.0 20.0 6.0 5.0 0.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 4.0 0.0 5.0 23.0 0.0 0.0 Grave
3 BEAUREPAIRE-EN-BRESSE 5 0.0 6.0 0.0 0.0 6.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 6.0 0.0 0.0 Pas Grave
4 CHALLES-LA-MONTAGNE 5 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4.0 6.0 0.0 0.0 Pas Grave

Diviser la dataset en train et test

In [136]:
X = data2.iloc[:, 1:-1].values
y = data2.iloc[:, -1].values
In [137]:
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
y = encoder.fit_transform(y)
In [138]:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)

Centrage/Reduction des donnés

In [139]:
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

Application des modeles de classification

In [140]:
from sklearn import metrics
import matplotlib.pyplot as plt
for i,j in models.iterrows():
    m = j["Classifier"]
    m.fit(X_train, y_train)
    y_pred = m.predict(X_test)
    cm = confusion_matrix(y_test, y_pred)
    auc = metrics.roc_auc_score(y_test == 3, y_pred)
    print(j["Classifier name"])
    print("AUC = ", auc)
    print(cm)
    print(classification_report(y_test,y_pred))
Logistic regression
AUC =  0.6294569227520577
[[3295  962 1548 1945]
 [1858 2305 2661  309]
 [ 663  614 5339  159]
 [2044  778  792 3788]]
             precision    recall  f1-score   support

          0       0.42      0.43      0.42      7750
          1       0.49      0.32      0.39      7133
          2       0.52      0.79      0.62      6775
          3       0.61      0.51      0.56      7402

avg / total       0.51      0.51      0.50     29060

Random forest
AUC =  0.6076187619686537
[[3552 1228 1118 1852]
 [1224 4544  787  578]
 [ 580 1459 4528  208]
 [2092 1326  247 3737]]
             precision    recall  f1-score   support

          0       0.48      0.46      0.47      7750
          1       0.53      0.64      0.58      7133
          2       0.68      0.67      0.67      6775
          3       0.59      0.50      0.54      7402

avg / total       0.56      0.56      0.56     29060

Les 2 modeles n'ont pas donnés des bonnes resultats

Prediction sur l'etat de l'accident (Motel ou non mortel)

Creation d'un modele de prediction de l'etat de l'accident (Motel ou non mortel)en se basant sur les variables explicatives de ce jeu données qui contient tous les accidents.

In [65]:
data_acc = pd.read_csv(r"C:\Users\Aymen\Desktop\DS_Data\final.csv")
C:\Users\Aymen\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:2785: DtypeWarning: Columns (15,17,18,21,23,58) have mixed types. Specify dtype option on import or set low_memory=False.
  interactivity=interactivity, compiler=compiler, result=result)
In [66]:
from scipy import stats
import random
#df.isna().any()
while data_acc.isna().any().any()==True:
    for i in data_acc.columns:
        data_acc[i] = data_acc[i].fillna(random.choice(data_acc[i]))
In [67]:
data_acc.head()
Out[67]:
Unnamed: 0 X Unnamed..0 Num_Acc an mois jour hrmn lum agg ... senc catv occutc obs obsm choc manv num_veh..55 dep_com NomCommune
0 1 0 1 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 1.0 1.0 A01 59011 ANNOEULLIN
1 2 1 2 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 8.0 10.0 B02 59011 ANNOEULLIN
2 3 2 3 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 1.0 1.0 A01 59011 ANNOEULLIN
3 4 3 4 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 8.0 10.0 B02 59011 ANNOEULLIN
4 5 4 5 200500000001 5 1 12 1900 3 2 ... 0.0 7 0 0.0 2.0 1.0 1.0 A01 59011 ANNOEULLIN

5 rows × 60 columns

Elimination des variables qualitative pour pouvoir créer un modele qui predicte si un accident est mortel ou non

In [68]:
data_acc.drop(['Unnamed: 0', 'adr', 'gps', 'num_veh..55', 'dep_com', 'NomCommune', 'num_veh', 'long', 'dep', 'voie', 'v2'], axis=1, inplace=True)

L'ajout d'une colonne qui decrit l'etat de l'accident

In [69]:
import numpy as np
data_acc['etatAccident'] = np.where(data_acc['grav'] ==2, 'Mortel', 'Non mortel')
In [70]:
X = data_acc.iloc[:, 1:-1].values
y = data_acc.iloc[:, -1].values
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
X_train
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
X_train
from sklearn.linear_model import LogisticRegression
model_lg = LogisticRegression()
model_lg.fit(X_train, y_train)
y_pred = model_lg.predict(X_test)
In [72]:
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_pred, y_test)
cm
Out[72]:
array([[    41,     54],
       [ 16211, 656902]], dtype=int64)
In [73]:
print(classification_report(y_test,y_pred))
             precision    recall  f1-score   support

     Mortel       0.43      0.00      0.01     16252
 Non mortel       0.98      1.00      0.99    656956

avg / total       0.96      0.98      0.96    673208

Le modele n'a pas donné des bonnes resultats

In [ ]:
 

Ségmentation

** Clustring **

data <- read.table(file=file.choose(), header = T, sep=",", dec = ".")

on a choisit de faire la segmentation en 4 clusters.

dataScaled <- scale(data[, 3:ncol(data)])
km <- kmeans(dataScaled, centers = 4)
km$size
## [1] 35825 35560  1216   144
data$km_cluster <- km$cluster
library(plyr)
## Warning: package 'plyr' was built under R version 3.5.1
ddply(data, ~km_cluster, numcolwise(mean))
##   km_cluster        X        an nb_acc_tot nb_acc_lum2 nb_acc_lum3
## 1          1 72949.94 14.153608   11.09664   0.7265318    1.338451
## 2          2 74607.07  7.395669   14.26682   0.8708380    1.877222
## 3          3 75257.99 10.816612  424.71382  23.2804276   17.646382
## 4          4 74491.29 10.465278 1896.29167  82.0972222   30.576389
##   nb_acc_lum4 nb_acc_lum5 nb_acc_catr2 nb_acc_catr3 nb_acc_catr4
## 1  0.07335659    1.025987    0.9192742     5.948248     2.622080
## 2  0.08174916    1.509252    1.8884702     6.833127     3.491845
## 3  4.43503289   80.816612   42.3519737    87.558388   225.453125
## 4 12.06944444  451.145833   95.7847222    77.791667  1527.777778
##   nb_acc_catr5 nb_acc_catr6 nb_acc_catr9 nb_acc_catu2 nb_acc_catu3
## 1   0.00837404   0.05113747    0.1032798     2.289658    0.4149616
## 2   0.01915073   0.07232846    0.2401294     3.171879    0.4455006
## 3   0.76233553   2.23766447    8.0912829    62.927632   23.6628289
## 4   1.78472222   4.06250000   62.2986111   233.868056  102.9097222
##   nb_acc_catu4 nb_acc_atm2 nb_acc_atm3 nb_acc_atm4 nb_acc_atm5 nb_acc_atm6
## 1  0.008457781     1.10113   0.2702303  0.08279135   0.1494766  0.02581996
## 2  0.008548931     1.40149   0.3497469  0.17634983   0.1530090  0.03481440
## 3  0.592927632    48.50905   9.1611842  2.94161184   2.5945724  0.98930921
## 4  2.305555556   195.25694  32.0208333  5.56944444  18.3055556  1.98611111
##   nb_acc_atm7 nb_acc_atm8 nb_acc_atm9 nb_acc_prof1 nb_acc_prof2
## 1   0.2029309   0.4211305  0.06752268     7.886336     1.739902
## 2   0.1721879   0.5951631  0.16223285    10.036755     2.161530
## 3   2.9580592  12.1118421  2.78536184   346.273849    45.798520
## 4   6.6527778  75.3888889  4.11111111  1498.590278   255.819444
##   nb_acc_prof3 nb_acc_prof4 nb_acc_grav2 nb_acc_grav3 nb_acc_grav4
## 1    0.2585066    0.1786462    0.4449686     3.048486     3.008095
## 2    0.3620079    0.2805399    0.5613611     3.738920     4.007790
## 3    6.9893092    4.1439145    2.9564145    51.689967   171.407072
## 4   27.5000000   19.9305556    7.4375000   144.118056   846.756944

Cluster 1 : caracteriser par un nombre elevé d’accident tres élevé et la majorites des accidents on etait a l’aube et la nuit avec un eclairage public allumé et les accidents etait sur la voie communale et sur une route plat
. Cluster 3 : caracteriser par des routes departementales


conclusion : il y a une forte saisonnalité dans nos données. Nous pouvons clairement voir que nous avons ici une saisonnalité hebdomadaire, donc une tendance qui se répète chaque semaine. Ce type de modèle est précieux car il nous permettra d’améliorer nos prévisions en fonction de ce qui s’est passé la semaine dernière, par exemple. Nous pouvons également noter une forte corrélation avec ce qui s'est passé la veille. Comme on peut le constater ici, on constate clairement une tendance où le nombre d'accidents diminue les vendredis et les dimanches et atteint son minimum le samedi. Les autres jours sont à peu près les mêmes (jours ouvrables).